Põhjalik juhend globaalsetele arendajatele Pythoni http.serveri (varem BaseHTTPServer) kohandamiseks lihtsamate API-de, dünaamiliste veebiserverite ja võimsate sisevahendite loomiseks.
Pythoni sisseehitatud HTTP-serveri meisterdamine: kohandamise põhjalik analüüs
Pythoni tähistatakse tema "patareid kaasas" filosoofia eest, pakkudes rikkalikku standardteeki, mis annab arendajatele võimaluse luua funktsionaalseid rakendusi minimaalse väliste sõltuvustega. Üks kõige kasulikumaid, kuid sageli tähelepanuta jäetud patareisid on sisseehitatud HTTP-server. Olgu te seda siis selle Python 3 nimega http.server
või selle Python 2 nimega BaseHTTPServer
teate, see moodul on värav veebiprotokollide mõistmiseks ja kergete veebiteenuste loomiseks.
Kuigi paljud arendajad kohtuvad sellega esmalt ühe reaga failide teenindamiseks kataloogis, peitub selle tegelik võimsus selle laiendatavuses. Selle peamisi komponente pärides saate muuta selle lihtsa failiserveri kohandatud veebirakenduseks, front-end arenduse jaoks mõeldud simuleeritud API-ks, IoT-seadmete jaoks andmete vastuvõtjaks või võimsaks sisevahendiks. See juhend viib teid põhitõdedest edasijõudnud kohandamiseni, andes teile selle fantastilise mooduli kasutamiseks teie enda projektides.
Põhitõed: lihtne server käsurealt
Enne koodi sukeldumist vaatame kõige tavalisemat kasutusjuhtumit. Kui teil on Python installitud, on teil juba veebiserver. Navigeerige terminali või käsuviiba abil mis tahes kataloogi oma arvutis ja käivitage järgmine käsk (Python 3 jaoks):
python -m http.server 8000
Koheselt on teil porti 8000 käivitatav veebiserver, mis teenindab teie praeguse asukoha faile ja alamkatalooge. Saate sellele oma brauserist juurde pääseda aadressil http://localhost:8000
. See on uskumatult kasulik:
- Failide kiireks jagamiseks kohalikus võrgus.
- Lihtsate HTML-, CSS- ja JavaScripti projektide testimiseks ilma keerulise seadistamiseta.
- Selle kontrollimiseks, kuidas veebiserver erinevaid päringuid käsitleb.
See ühe rea käsk on aga vaid jäämäe tipp. See käitab eelnevalt ehitatud, üldist serverit. Kohandatud loogika lisamiseks, erinevate päringutüüpide käsitlemiseks või dünaamilise sisu loomiseks peame kirjutama oma Pythoni skripti.
Põhikomponentide mõistmine
Selle mooduliga loodud veebiserver koosneb kahest peamisest osast: server ja haldur. Nende erinevate rollide mõistmine on tõhusa kohandamise võti.
1. Server: HTTPServer
Serveri ülesanne on kuulata sissetulevaid võrguühendusi kindlal aadressil ja pordil. See on mootor, mis aktsepteerib TCP-ühendusi ja edastab need haldurile töötlemiseks. http.server
moodulis tegeleb sellega tavaliselt HTTPServer
klass. Loote selle eksemplari, esitades serveri aadressi (tuppel nagu ('localhost', 8000)
) ja halduriklassi.
Selle peamine vastutus on võrgu pesa haldamine ja päring-vastuse tsükli korraldamine. Enamiku kohanduste jaoks ei pea te HTTPServer
klassi ennast muutma, kuid on oluline teada, et see töötab ja juhib kõike.
2. Haldur: BaseHTTPRequestHandler
Siin toimub maagia. Haldur vastutab sissetuleva HTTP-päringu analüüsimise, kliendi soovide mõistmise ja sobiva HTTP-vastuse genereerimise eest. Iga kord, kui server saab uue päringu, loob see teie halduriklassi eksemplari selle töötlemiseks.
http.server
moodul pakub mõningaid eelnevalt ehitatud haldureid:
BaseHTTPRequestHandler
: See on kõige elementaarsem haldur. See analüüsib päringut ja päiseid, kuid ei tea, kuidas vastata konkreetsetele päringumeetoditele nagu GET või POST. See on täiuslik alusklass, millest pärida, kui soovite kõike nullist ehitada.SimpleHTTPRequestHandler
: See pärinebBaseHTTPRequestHandler
-st ja lisab loogika praegusest kataloogist failide teenindamiseks. Kui käivitatepython -m http.server
, kasutate seda haldurit. See on suurepärane alguspunkt, kui soovite lisada kohandatud loogikat vaikimisi failiteeninduse käitumisele.CGIHTTPRequestHandler
: See laiendabSimpleHTTPRequestHandler
-i, et käsitleda ka CGI-skripte. See on tänapäevases veebiarenduses vähem levinud, kuid kuulub teegi ajalukku.
Peaaegu kõigi kohandatud serveriülesannete jaoks hõlmab teie töö uue klassi loomist, mis pärineb BaseHTTPRequestHandler
-st või SimpleHTTPRequestHandler
-st ja selle meetodite ülekatmist.
Teie esimene kohandatud server: "Tere, maailm!" näide
Liikugem käsurealt kaugemale ja kirjutame lihtsa Pythoni skripti serveri jaoks, mis vastab kohandatud sõnumiga. Pärime BaseHTTPRequestHandler
-st ja rakendame meetodi do_GET
, mida kutsutakse automaatselt kõigi HTTP GET-päringute käsitlemiseks.
Looge fail nimega custom_server.py
:
# Kasutage Python 3 jaoks http.server
from http.server import BaseHTTPRequestHandler, HTTPServer
import time
hostName = "localhost"
serverPort = 8080
class MyServer(BaseHTTPRequestHandler):
def do_GET(self):
# 1. Saada vastuse olekukood
self.send_response(200)
# 2. Saada päised
self.send_header("Content-type", "text/html")
self.end_headers()
# 3. Kirjuta vastuse sisu
self.wfile.write(bytes("<html><head><title>Minu kohandatud server</title></head>", "utf-8"))
self.wfile.write(bytes("<p>Päring: %s</p>" % self.path, "utf-8"))
self.wfile.write(bytes("<body>", "utf-8"))
self.wfile.write(bytes("<p>See on kohandatud server, loodud Pythoni http.server-iga.</p>", "utf-8"))
self.wfile.write(bytes("</body></html>", "utf-8"))
if __name__ == "__main__":
webServer = HTTPServer((hostName, serverPort), MyServer)
print(f"Server käivitatud http://{hostName}:{serverPort}")
try:
webServer.serve_forever()
except KeyboardInterrupt:
pass
webServer.server_close()
print("Server peatatud.")
Selle käivitamiseks käivitage terminalis python custom_server.py
. Kui külastate brauseris http://localhost:8080
, näete oma kohandatud HTML-sõnumit. Kui külastate teist teed, näiteks http://localhost:8080/some/path
, kajastab sõnum seda teed.
Vaatame üle meetodi do_GET
:
self.send_response(200)
: See saadab HTTP olekur rea.200 OK
on standardvastus edukale päringule.self.send_header("Content-type", "text/html")
: See saadab HTTP päise. Siin ütleme brauserile, et saadetav sisu on HTML. See on brauserile lehe õigeks kuvamiseks hädavajalik.self.end_headers()
: See saadab tühja rea, märkides HTTP päiste lõppu ja vastuse sisu algust.self.wfile.write(...)
:self.wfile
on faililaadne objekt, kuhu saate kirjutada oma vastuse sisu. See ootab baitide, mitte stringide, seega peame oma HTML-stringi kodeerima baitideks, kasutadesbytes("...", "utf-8")
.
Edasijõudnud kohandamine: praktilised retseptid
Nüüd, kui olete põhitõed mõistnud, uurigem võimsamaid kohandusi.
POST-päringute käsitlemine (do_POST
)
Veebirakendused peavad sageli andmeid vastu võtma, näiteks HTML-vormilt või API-kutsest. Seda tehakse tavaliselt POST-päringuga. Selle käsitlemiseks ülekatate meetodi do_POST
.
Meetodi do_POST
sees peate lugema vastuse sisu. Selle sisu pikkus on märgitud päises Content-Length
.
Siin on näide haldurist, mis loeb POST-päringust JSON-andmeid ja kordab neid tagasi:
import json
from http.server import BaseHTTPRequestHandler, HTTPServer
class APIServer(BaseHTTPRequestHandler):
def _send_cors_headers(self):
"""Saadab päiseid, et lubada piiriüleseid päringuid"""
self.send_header("Access-Control-Allow-Origin", "*")
self.send_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
self.send_header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type")
def do_OPTIONS(self):
"""Käsitleb eelkäivituslikke CORS-päringuid"""
self.send_response(200)
self._send_cors_headers()
self.end_headers()
def do_POST(self):
# 1. Lugege päise Content-Length
content_length = int(self.headers['Content-Length'])
# 2. Lugege vastuse sisu
post_data = self.rfile.read(content_length)
# Näitena logime vastu võetud andmed
print(f"Vastu võetud POST-andmed: {post_data.decode('utf-8')}")
# 3. Töötle andmeid (siin kordame seda tagasi JSON-na)
try:
received_json = json.loads(post_data)
response_data = {"status": "success", "received_data": received_json}
except json.JSONDecodeError:
self.send_response(400) # Halb päring
self.end_headers()
self.wfile.write(bytes('{"error": "Kehtetu JSON"}', "utf-8"))
return
# 4. Saada vastus
self.send_response(200)
self._send_cors_headers()
self.send_header("Content-type", "application/json")
self.end_headers()
self.wfile.write(json.dumps(response_data).encode("utf-8"))
# Peamine käivitusplokk jääb samaks...
if __name__ == "__main__":
# ... (kasutage sama HTTPServer seadistust kui varem, kuid APIServer-iga haldurina)
server_address = ('localhost', 8080)
httpd = HTTPServer(server_address, APIServer)
print('Serveri käivitamine pordil 8080...')
httpd.serve_forever()
Märkus CORS-i kohta: meetod do_OPTIONS
ja funktsioon _send_cors_headers
on kaasatud piiriüleste ressursside jagamise (CORS) käsitlemiseks. See on sageli vajalik, kui kutsute oma API-d teisest allikast (domeen/port) teenindatavast veebilehest.
Lihtsa API loomine JSON-vastustega
Laiendame eelmist näidet, et luua server põhijuhistamisega. Ressursi, mida klient soovib, ja vastavalt sellele vastata, määramiseks saame uurida atribuuti self.path
. See võimaldab meil luua ühe serveri piires mitu API-lõpp-punkti.
import json
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import urlparse, parse_qs
# Simuleeritud andmed
users = {
1: {"name": "Alice", "country": "Canada"},
2: {"name": "Bob", "country": "Australia"}
}
class APIHandler(BaseHTTPRequestHandler):
def _set_headers(self, status_code=200):
self.send_response(status_code)
self.send_header("Content-type", "application/json")
self.send_header("Access-Control-Allow-Origin", "*")
self.end_headers()
def do_GET(self):
parsed_path = urlparse(self.path)
path = parsed_path.path
if path == "/api/users":
self._set_headers()
self.wfile.write(json.dumps(list(users.values())).encode("utf-8"))
elif path.startswith("/api/users/"):
try:
user_id = int(path.split('/')[-1])
user = users.get(user_id)
if user:
self._set_headers()
self.wfile.write(json.dumps(user).encode("utf-8"))
else:
self._set_headers(404)
self.wfile.write(json.dumps({"error": "Kasutajat ei leitud"}).encode("utf-8"))
except ValueError:
self._set_headers(400)
self.wfile.write(json.dumps({"error": "Kehtetu kasutaja ID"}).encode("utf-8"))
else:
self._set_headers(404)
self.wfile.write(json.dumps({"error": "Ei leitud"}).encode("utf-8"))
# Peamine käivitusplokk nagu varem, kasutades APIHandler-it
# ...
Selle halduriga on teie serveril nüüd algeline suunamisüsteem:
- GET-päring aadressile
/api/users
tagastab kõigi kasutajate loendi. - GET-päring aadressile
/api/users/1
tagastab Alice'i üksikasjad. - Mis tahes muu tee põhjustab 404 Mitte leitud vea.
Failide ja dünaamilise sisu ühine teenindamine
Mis siis, kui soovite sama serveriga dünaamilist API-t, kuid ka staatilisi faile (nagu index.html
) teenindada? Lihtsaim viis on pärida SimpleHTTPRequestHandler
-st ja suunata selle vaikimisi käitumisele, kui päring ei vasta teie kohandatud teedele.
super()
funktsioon on siin teie parim sõber. See võimaldab teil kutsuda ülemklassi meetodit.
import json
from http.server import SimpleHTTPRequestHandler, HTTPServer
class HybridHandler(SimpleHTTPRequestHandler):
def do_GET(self):
if self.path == '/api/status':
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
response = {'status': 'ok', 'message': 'Server töötab'}
self.wfile.write(json.dumps(response).encode('utf-8'))
else:
# Kõigi muude teede jaoks lülitage tagasi vaikimisi failiteeninduse käitumisele
super().do_GET()
# Peamine käivitusplokk nagu varem, kasutades HybridHandler-it
# ...
Nüüd, kui loote samasse kataloogi faili index.html
ja käivitate selle skripti, teenindab http://localhost:8080/
külastus teie HTML-faili, samas kui http://localhost:8080/api/status
külastus tagastab teie kohandatud JSON-vastuse.
Märkus Python 2 kohta (BaseHTTPServer
)
Kuigi Python 2 enam ei toetata, võite kokku puutuda vanema koodiga, mis kasutab selle HTTP-serveri versiooni. Kontseptsioonid on identsed, kuid moodulinimed on erinevad. Siin on kiire tõlkeguide:
- Python 3:
http.server
-> Python 2:BaseHTTPServer
,SimpleHTTPServer
- Python 3:
socketserver
-> Python 2:SocketServer
- Python 3:
from http.server import BaseHTTPRequestHandler
-> Python 2:from BaseHTTPServer import BaseHTTPRequestHandler
Meetodinimed (do_GET
, do_POST
) ja põhiline loogika jäävad samaks, muutes vanade skriptide portimise Python 3-sse suhteliselt lihtsaks.
Tootmisküsimused: millal edasi liikuda
Pythoni sisseehitatud HTTP-server on fenomenaalne tööriist, kuid sellel on oma piirangud. On oluline mõista, millal see on õige valik ja millal peaksite jõudma robustsema lahenduseni.
1. Konkurents ja jõudlus
Vaikimisi on HTTPServer
üheskeermeline ja töötleb päringuid järjestikku. Kui üks päring võtab pikalt aega, blokeerib see kõik muud sissetulevad päringud. Veidi edasijõudnud kasutusjuhtumite jaoks saate kasutada socketserver.ThreadingMixIn
mitmelõimelise serveri loomiseks:
from socketserver import ThreadingMixIn
from http.server import HTTPServer
class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
"""Käitle päringuid eraldi niidis."""
pass
# Oma peamises plokis kasutage seda HTTPServer asemel:
# webServer = ThreadingHTTPServer((hostName, serverPort), MyServer)
Kuigi see aitab konkurentsi, pole see ikka veel ette nähtud suure jõudlusega, suure liiklusega tootmiskeskkondade jaoks. Täielikud veebiraamistikud ja rakenduserverid (nagu Gunicorn või Uvicorn) on optimeeritud jõudluse, ressursihaldamise ja mastaapsuse jaoks.
2. Turvalisus
http.server
ei ole ehitatud turvalisust esmase fookusena. Sellel puuduvad sisseehitatud kaitsemeetmed levinud veebiohtude, nagu Cross-Site Scripting (XSS), Cross-Site Request Forgery (CSRF) või SQL-i süstimise vastu. Tootmiskvaliteediga raamistikud nagu Django, Flask ja FastAPI pakuvad neid kaitsemeetmeid kohe.
3. Funktsioonid ja abstraktne tase
Teie rakenduse kasvades soovite funktsioone nagu andmebaasi integratsioon (ORM-id), mallimootorid, keerukas suunamine, kasutaja autentimine ja vahevara. Kuigi võiksite seda kõike ise ehitada http.server
peale, leiutaksite põhimõtteliselt veebiraamistiku uuesti. Raamistikud nagu Flask, Django ja FastAPI pakuvad neid komponente hästi struktureeritud, lahingutestitud ja hooldataval viisil.
Kasutage http.server
järgmiste jaoks:
- HTTP õppimine ja mõistmine.
- Kiire prototüüpimine ja kontseptsioonide tõestamine.
- Lihtsate, ainult sisekasutuseks mõeldud tööriistade või juhtpaneelide loomine.
- Simuleeritud API-serverite loomine front-end arenduse jaoks.
- Kerged andmekogumisotsad IoT või skriptide jaoks.
Liikuge raamistiku juurde järgmiste jaoks:
- Avalikult kasutatavad veebirakendused.
- Keerulised API-d autentimise ja andmebaasi interaktsioonidega.
- Rakendused, kus turvalisus, jõudlus ja mastaapsus on kriitilise tähtsusega.
Kokkuvõte: lihtsuse ja kontrolli võim
Pythoni http.server
on tunnistus keele praktilisest disainist. See pakub lihtsat, kuid võimsat alust kõigile, kes peavad veebiprotokollidega töötama. Selle päringuhaldurite kohandamise õppides saate peene kontrolli päring-vastuse tsükli üle, mis võimaldab teil luua laia valikut kasulikke tööriistu ilma täieliku veebiraamistiku lisakuludeta.
Järgmisel korral, kui vajate kiiret veebiteenust, simuleeritud API-t või soovite lihtsalt HTTP-ga katsetada, pidage meeles seda mitmekülgset moodulit. See on rohkem kui lihtsalt failiserver; see on teie veebipõhiste loomingute tühjad lõuendid, mis on kaasas otse Pythoni standardteegis.